home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 1 / Meeting Pearls Vol 1 (1994).iso / installed_progs / text / faqs / macintosh.programming-faq < prev    next >
Encoding:
Internet Message Format  |  1994-05-15  |  64.7 KB

  1. Subject: The Mac Programming Public Domain FAQ Answer sheet.
  2. Newsgroups: comp.sys.mac.programmer,comp.answers,news.answers
  3. From: d88-jwa@dront.nada.kth.se (Jon Wätte)
  4. Date: 13 May 1994 16:53:05 GMT
  5.  
  6. Archive-name: macintosh/programming-faq 
  7.  
  8. The Public Domain Mac Programming FAQ Answer sheet.
  9. Last update: 940513
  10.  
  11. This sheet was started by and is presently maintained by Jon 
  12. W{tte, whom you may reach as h+@nada.kth.se. If there is 
  13. anything you find errant, missing or in need of an update, 
  14. please send me your submission and I will include it (I can't 
  15. promise correct attributions, but I will try) All FAQ Answer 
  16. submissions sent to me will be considered to be in the public 
  17. domain unless stated otherwise (in which case they will not be 
  18. included in this FAQ sheet) 
  19.  
  20. This sheet is currently archived on nada.kth.se where you can 
  21. reach it using afs as /afs/nada.kth.se/public/ftp/pub/hacks/mac-f
  22. aq/CSMP_PD_FAQ or using anonymous FTP (GIVE YOUR E-MAIL ADDRESS 
  23. AS PASSWORD!) as pub/hacks/mac-faq/CSMP_PD_FAQ 
  24.  
  25. I will try to update this sheet every three weeks or so.
  26.  
  27. This sheet is divided into several parts; each of which covers a 
  28. general area which often gets asked about in the Internet 
  29. newsgroup comp.sys.mac.programmer. Please download a copy of 
  30. this answer sheet and search it before you post to the 'net, to 
  31. help reduce bandwidth. 
  32.  
  33. There is NO or VERY LIMITED error checking in these code 
  34. examples, FOR BREVITY ONLY. You should make sure you ALWAYS 
  35. check ALL return codes, and handle any that you are not prepared 
  36. to deal with appropriately. 
  37.  
  38. The coding style used in the example C code is my own, and 
  39. you'll have to live with it.
  40.  
  41. The groups are (you may search for *<number>* to jump directly 
  42. to a group with its questions and answers) 
  43.  
  44. 0) Development and debugging tools and documentation for the Mac 
  45. 1) Files and the File Manager 
  46. 2) Serial ports 
  47. 3) TCP/IP and sockets 
  48. 4) AppleEvents and the Apple Object Model 
  49. 5) AppleScript
  50. 6) Drawing using QuickDraw 
  51. 7) Drawing NOT using QuickDraw (aka directly to screen) 
  52. 8) Cache issues and other processor differences 
  53. 9) What about pre-emptive multitasking? 
  54. 10) Handles; they are driving me crazy; Memory issues 
  55. 11) _Gestalt and compatibility 
  56. 12) Standalone code and dynamic linking 
  57. 13) Keyboard & Mouse for Games and Screen Savers 
  58. 14) QuickTime 
  59. 15) Windows, Menus, Dialogs
  60. 16) Ice Cream and Frozen Yoghurt 
  61. 17) TextEdit
  62.  
  63. *0* Development and debugging tools for the Macintosh 
  64.  
  65. 0.1) Q: What do I need to start writing Macintosh software? 
  66.  
  67. A: A Mac, a lot of time, and a few hundred $. Although you can 
  68. develop software on a Classic-type machine, it is not to be 
  69. attempted by the weak of heart or stressed of time. If you're 
  70. doing paid work and/or work for a company, a Quadra-class 
  71. machine or Centris 650 or better is almost a must; remember that 
  72. your time costs your employer much more than just your salary. 8 
  73. MB is a minimum to run at all comfortably, and Virtual Memory is 
  74. not suited for development work. Similarly; if you don't have at 
  75. least 20 MB free on your hard disk (40 MB for MPW) you need to 
  76. buy more space. 
  77.  
  78. You need a development system such as Think C, CodeWarrior C++, 
  79. MPW C or Prograph, you need at least some of the New Inside Mac 
  80. books (Toolbox Essentials, Files, Memory come to mind) and a 
  81. good entry-level third-party book may help. 
  82.  
  83. Once you are up to speed on the general layout of the Mac and 
  84. its toolboxes, you should call APDA and order the monthly 
  85. developer mailing, which will give you a CD chock full of 
  86. documentation, utilities and system software once a month. You 
  87. will also, obviously, need a CD player; one of which Apple's own 
  88. CD300 is a very good buy at the time of writing this. If you 
  89. don't have the dough for the monthly mailing ($250/year) you can 
  90. order a _develop_ subscription; this quarterly magazine 
  91. ($30-$50/year) comes with a CD containing all Inside Mac 
  92. documentation.
  93.  
  94. Another tool which many find a must-have is the Think Reference 
  95. version 2.0.1, containing reference material on the most used 
  96. parts of the Mac toolbox with lightning-fast look-up and mostly 
  97. correct usage hints and code snippets. 
  98.  
  99. 0.2) Q: What is the most used Macintosh development language? 
  100.  
  101. A: Out of products on the market, I have no idea; both MPW and 
  102. Think products appear to be used. Lately, CodeWarrior has come 
  103. out of nowhere and grabbed a large share of the market 
  104. visibility because they have the fastest compiler and they 
  105. generate PowerPC code as well as 68K code. Among hobbyists, the 
  106. Think products from Symantec are most popular because of the low 
  107. price, and steep educational discounts, and, of course, the 
  108. easily approachable interface! 
  109.  
  110. The Think C linker only strips dead code on a FILE level basis 
  111. (and this is when you turn on "Smart Linking") The MPW linker 
  112. (of no specified IQ, as someone so eloquently put it :-) strips 
  113. dead code by the function, as does CodeWarrior. That may be part 
  114. of the reason the Think C linker is ten times faster than the 
  115. MPW linker - but then how do you explain the CodeWarrior linker,
  116. which links like the MPW linker, but at speeds approaching
  117. Think C?
  118.  
  119. In the beginning, the Mac was programmed using Mc68000 assembly 
  120. or Pascal; this was reflected in the Old Inside Mac volumes 
  121. which only gave Pascal-style and assembly-style interfaces to 
  122. the Mac toolbox. These days, Apple tells us to use C or even 
  123. better C++ for developing new applications, as that will speed 
  124. up the transition to PowerPC and also coming cross-platform 
  125. efforts. (Language Systems have a Pascal for PowerPC product 
  126. now, but I don't know about pricing or quality)
  127.  
  128. There are also at least two Fortran compilers, at least three 
  129. SmallTalk implementations (ObjectWorks, SmallTalk/V and 
  130. SmallTalkAgents), a world-class LISP/CLOS implementation 
  131. (Macintosh Common Lisp 2.0) and a Modula/2 implementation. 
  132. Apparently, using Envy/packager, you can strip out unused code 
  133. pretty effectively from Digitalk and PP apps, which are then 
  134. smaller (and of course more memory efficient) than C++ apps. 
  135.  
  136. Metrowerks have a Pascal and a Modula II compiler. They're
  137. building C and C++ for both 68k and coming PPC Macs, and
  138. will also have a PowerPC Pascal.
  139.  
  140. CSI has MacForth, of which I only know the name and someone who 
  141. says it's pretty good.
  142.  
  143. There is another good Common Lisp implementation: Procyon Common 
  144. Lisp. I don't know if it is actively supported, but Procyon CL 
  145. is also available for DOS, OS/2 and Windows (as Allegro CL/PC) 
  146. and actively developed. 
  147.  
  148. 0.3) Q: Where do I find a public domain C compiler for the Mac. 
  149. Is there a GCC for the mac? What about the FSF boycott of Apple 
  150. products? 
  151.  
  152. A: There is no really good solution for a "for-free" C 
  153. development system for the Mac. GCC has been ported, but 
  154. requires the MPW shell and MPW assembler to run; these have to 
  155. be bought from APDA. There is a standalone port of GCC 1.37 on 
  156. nic.switch.ch:software/mac/src/think_c. There was a freely 
  157. available C compiler called Harvest C, which was somewhat 
  158. unstable but usable for smaller programs; it was abandoned by 
  159. the original author Eric W Sink because of a lack of time and 
  160. later taken up by the TopSoft project.
  161.  
  162. The FSF boycott of Apple products means they will not talk to 
  163. you if you ask them for help in doing a Mac port, and they will 
  164. not incorporate your changes into their main code base. However, 
  165. they still allow others to port GNU stuff to the Mac, and it has 
  166. been done with most of the application-like GNU programs (bison, 
  167. flex, perl (not really part of GNU), ...) 
  168.  
  169. gcc-1.37r14 V1.1 standalone is available for ftp at the address below.
  170.  
  171. (A) nic.switch.ch:software/mac/src/think_c/GCC_1.37.1r14.sit.bin
  172. (B) nic.switch.ch:software/mac/src/think_c/GCC_1.37.1r14_src.sit.bin
  173. (C) nic.switch.ch:software/mac/src/think_c/GCC_1.37.1r14_libsrc.sit.bin
  174. (D) nic.switch.ch:software/mac/src/think_c/GCC_1.37.1r14_includes.sit.bin
  175.  
  176. Exhibit (A) will be of interest to users who wish to play with an actual
  177. application. This can not be described as finished, but it is at least
  178. functional. Comments and feedback by e-mail to jrrk@camcon.co.uk are
  179. invited. Exhibit (B) will be of interest to those who like to tinker with
  180. source code and crib ideas for their own programs.
  181. Exhibit (C) will be useful to those who need a library to simplify porting
  182. of code from UNIX or who are otherwise fed up with the incompatabilities of
  183. the standard C library provided with THINK C. It is also needed to build
  184. (B) into a complete application, and also provides the basis of the object
  185. libraries supplied with (A).
  186. Exhibit (D) are the conventional (i.e. non mac toolbox) headers that are
  187. needed to compile the source code and for anyone who would like to write
  188. ANSI-C programs. However the number of hacks needed to gcc to make it
  189. support mac native toolbox applications is likely to make it unreliable as
  190. an ANSI compiler. For this purpose, I have found MacMiNT to be a better
  191. alternative.
  192.  
  193. Highly recommended is to get the toolbox includes for MPW 3.2 and the
  194. 'spinside macintosh' hypercard stack from ftp.apple.com These will give
  195. users an idea of how to go about programming stand-alone Mac applications.
  196.  
  197. 0.4) Q: Are there any other free Mac development platforms? 
  198.  
  199. A: Yerk and Mops. These are object oriented languages based on 
  200. the old product Neon which itself was based on Forth. They are 
  201. available with Manuals at oddjob.uchicago.edu (anonymous FTP). 
  202.  
  203. Plus, there's MacGambit, MacScheme, xlisp, and MacMETH which is 
  204. the actual ETH (read: Nick Wirth's group) Modula 2, all for free 
  205. via FTP.
  206.  
  207. And OpenProlog. And SIOD (Scheme in One Defun) And [mail in more 
  208. if you dare]
  209.  
  210. 0.5) Q: What's the difference between the MPW and Think 
  211. environments? 
  212.  
  213. A: The main difference is that Think is an integrated 
  214. environment, while MPW provides you with a command-line shell 
  215. for your Mac and tools to use in it. MPW also has a slightly 
  216. higher systems demand and a much slower linker. 
  217.  
  218. The good thing about MPW is that you can write scripts and make 
  219. files to do anything you want in the way you want it. Think 
  220. still doesn't have a viable solution to do a build that requires 
  221. more than one link operation, or has more than one destination 
  222. file. 
  223.  
  224. For the MPW environment, there are three source level debuggers; 
  225. SADE, SourceBug and Voodoo Monkey. The latter is an experimental 
  226. debugger with support for threads debugging; the middle is 
  227. bundled with MPW while SADE has to be bought separately (but is 
  228. fully scriptable in its own scripting language) 
  229.  
  230. The Think environments have their own integrated debuggers; the 
  231. Think Pascal one has a lot of useful features while the Think 
  232. C/C++ one is a little more basic (but is gaining in 
  233. functionality with each release) Stepping through source code 
  234. and looking at variables is generally faster and easier in Think 
  235. than the MPW debuggers. 
  236.  
  237. Any commercial Mac developer should have both Think and MPW of 
  238. whatever language they prefer (Pascal, C or C++) 
  239.  
  240. 0.6) Q: What is a good low-level debugger for the Mac? 
  241.  
  242. A: MacsBug is freely available for ftp from ftp.apple.com; log 
  243. in as user anonymous and give your FULL e-mail address as 
  244. password. MacsBug is your basic monitor-type debugger that takes 
  245. a few hundred Ks of memory, and lets you break, step, 
  246. disassemble, look at the stack etc of most anything running on 
  247. your Mac. Since it's free (it's also on the developer CDs) and 
  248. provides most of the functionality you need, this is a popular 
  249. choice. 
  250.  
  251. TMON is another debugger which sports a more mac-like interface; 
  252. it provides windows and uses the mouse. It can take as little or 
  253. much memory as you want by excluding or including certain areas 
  254. of functionality. A nice touch is the 6502 disassembler that you 
  255. can use to de-bug the code the IOP processors run on the Mac 
  256. IIfx and Quadra 900/950. 
  257.  
  258. Jasik Designs have a debugger called The Debugger which can do 
  259. both low- and high-level debugging, with or without source and 
  260. for all types of code, application, code resources, everything. 
  261. This is the debugger of choice for many large developers because 
  262. of its high power and many features not found anywhere else. 
  263. However; newcomers beware! This is the Lamborghini of debuggers; 
  264. if you know how to drive it, it is the fastest way from A to B; 
  265. if you don't, you'll just end up in the ditch. As a lady put it:
  266. "The man wouldn't know a user interface if it bit him in the
  267. rear."
  268.  
  269. 0.7) Q: Are there any visual developments environments for the 
  270. Mac (comparable to Visual C++)?
  271.  
  272. A: There is no Visual C++ as such. However, there is a C++ 
  273. parser/editor called ObjectMaster which provides good browsing 
  274. and editing capabilities if you already have a C++ compiler. 
  275. Think C++ also comes with a browser built-in, and you can draw 
  276. dialogs/windows using plain old ResEdit, even for your custom 
  277. view types. 
  278.  
  279. Symantec C++ 7.0 also bundles a view editor/code generator called
  280. Visual Architect; it is fairly complete and has a good level of
  281. integration into the Think Project Manager.
  282.  
  283. AppMaker is a GUI builder/code generator.  Granted, it's not as 
  284. nice as VC++, but it's quite a product in any case.
  285.  
  286. MarksMan version 3.0 has totally revised TCL templates, and now
  287. generates well-thought-out TCL code. It can also generate ANSI
  288. C code etc.
  289.  
  290. Also, Neuron Data has their UI tool called Open Interface, which 
  291. is better than VC++ and creates code portable across 35 
  292. platforms. Unfortunately it's $2500 per developer per platform. 
  293. (There's also two other cross-platform products called XVT and 
  294. Galaxy, the former has gotten flak on UseNet while the latter 
  295. reportedly has decent networking support)
  296.  
  297. There is a fully visual, dynamic, object oriented data-flow-drive
  298.   n programming language for the Mac called Prograph Corporate 
  299. Programming Something-or-other (CPX). It is expensive ($1500) 
  300. but offers a built-in database, easy interfaces to existing data 
  301. bases, very high productivity in implement-test-debug cycling 
  302. and also offers cross-platform capabilities (it comes with a 
  303. class library which, when your code is written using it, works 
  304. under Windows after re-compilation) 
  305.  
  306. There is a crossing between SmallTalk and C++ that is called 
  307. Component Workshop; although it seems large and slowly evolving, 
  308. it does offer some promising features not found in C++ itself. 
  309.  
  310. There is also something called SmallTalkAgents that makes it 
  311. easy to create Mac applications using SmallTalk. If you'd rather 
  312. do Common Lisp, Macintosh Common Lisp offers a Common Lisp 
  313. Object System with support for most Mac interface items; you can 
  314. edit code while it is running and build stand-alone 
  315. applications. 
  316.  
  317. However, all of these tools generate rather larger binaries with 
  318. larger system demands than a program written in C. On the other 
  319. hand; C++ programs require more memory and disk space than 
  320. programs written in assembly. It's a trade-off, and I believe 
  321. this type of tools is the wave of the near future. 
  322.  
  323. 0.8) Q: What class libraries are there for the Mac? 
  324.  
  325. A: Apart from the libraries mentioned above, there are three 
  326. contenders: MacApp, TCL, and OOPC. On the horizon may be 
  327. Bedrock. 
  328.  
  329. MacApp is a heavy-duty class library that has tons of features 
  330. and a steep learning curve; it runs under MPW with Pascal or 
  331. C++, and also under Think Pascal 4.0 A major application written 
  332. in MacApp is PhotoShop. 
  333.  
  334. TCL stands for Think Class Library and comes with Think Pascal, 
  335. C or C++. It is a smaller library that still fills most peoples 
  336. needs; since Think C implements a subset of C++ (the most 
  337. important OO concepts such as virtual functions and inheritance) 
  338. and the TCL is carefully written not to take advantage of any 
  339. C++ features not in Think C, you can use it with Think C. A 
  340. major application written in TCL is Lotus 1-2-3. 
  341.  
  342. OOPC is a newcomer in the field, and uses plain ANSI C. However, 
  343. it mangles the pre-processor to provide you with a system with 
  344. full inheritance, virtual functions, and dynamic re-binding of 
  345. functions for classes or individual objects. Start-up is slow, 
  346. since all "linking" of virtual functions and classes is made at 
  347. run-time, but performance otherwise is good. A Windows version 
  348. is promised for later this year. 
  349.  
  350. 0.9) Q: How should I debug and test my software? 
  351.  
  352. A: Get ahold of, and install, the extensions DoubleTrouble, 
  353. DisposeResource and EvenBetterBusError. They will catch 80% of 
  354. any memory related bugs you may have, including many bugs that 
  355. follow NULL handles or pointers. 
  356.  
  357. A low-level debugger is required, and while you install it, 
  358. install the "leaks" dcmd which will help you catch memory leaks 
  359. in your application. All of these tools are available from 
  360. ftp.apple.com. 
  361.  
  362. 0.10) Q: Are there any good Mac programming magazines?
  363.  
  364. A: One Mac programming magazine I know of is "MacTech"
  365. (formerly MacTutor) It is focused on Mac programming on various
  366. levels. Not all their methods are guaranteed to stay compatible
  367. though :-)
  368.  
  369. Another VERY GOOD Magazine is _develop_ which is put out by Apple
  370. four times a year; it comes with a CD containing code for all
  371. articles ever published in _develop_, and a lot of documentation
  372. and system software freebies as well. $30/year in the US.
  373.  
  374. *1* Files and the File Manager 
  375.  
  376. 1.1) Q: How do I tell fopen() to open a file the user has 
  377. selected using StandardGetFile? 
  378.  
  379. A: The "standard" ANSI C file functions are less than well 
  380. suited for the Macintosh way of doing things. However, if you 
  381. are doing a port for your own enjoyment and benefit (or maybe 
  382. for in-house work) you can use the following function: (see 
  383. below about converting a wdRefNum into a vRefNum/parID pair) 
  384.  
  385. *code*
  386. FILE *
  387. fopen_mac ( short vRefNum , long parID , char * fileName , char * mode ) {
  388.  
  389. short oldVol ;
  390. short aVol ;
  391. long aDir , aProc ;
  392. FILE * ret = NULL ;
  393.  
  394.     if ( GetVol ( NULL , & oldVol ) ) {
  395.         return NULL ;
  396.     }
  397.     if ( GetWDInfo ( oldVol , & aVol , & aDir , & aProc ) ) {
  398.         return NULL  ;
  399.     }
  400.     if ( HSetVol ( NULL , vRefNum , parID ) ) {
  401.         return NULL ;
  402.     }
  403.     ret = fopen ( fileName , mode ) ;
  404.     if ( HSetVol ( aVol , aDir ) ) {
  405.         /* an error we can't currently handle */
  406.     }
  407.     if ( SetVol ( oldVol ) ) {
  408.         /* an error we can't currently handle */
  409.     }
  410.     return ret ;
  411. }
  412. *end*
  413.  
  414. All of the above is necessary for one reason or another - if you 
  415. are interested, by all means look HSetVol up in Think Reference 
  416. 2.0 or New Inside Mac: Files. 
  417.  
  418. In older versions of MPW; this wouldn't work since the MPW 
  419. libraries used to do a GetVol and explicitly use that value by 
  420. itself. 
  421.  
  422. 1.2) Q: When can I use the HOpen, HCreate etc file calls? Are 
  423. they only System 7 calls? 
  424.  
  425. A: All the HXxx calls that take a vRefNum and parID as well as 
  426. the file name are implemented in glue that works on any system 
  427. that has HFS (meaning 3.2 and up with the HD20 INIT, and all 
  428. systems from System 6 and up) 
  429.  
  430. The glue is available in MPW 3.2 and up, and Think C 5.0 and up. 
  431. This goes for all HXxx calls except HOpenDF; therefore, if you 
  432. are interested in System 6 compatibility, use HOpen instead and 
  433. make sure you don't allow file names beginning with a period. 
  434.  
  435. 1.3) Q: Why do you say wdRefNum sometimes and vRefNum sometimes? 
  436. Why do you say parID sometimes and dirID sometimes? 
  437.  
  438. A: When the Mac first made an appearance in 1984, it identified 
  439. files by using a vRefNum (volume reference number meaning a 
  440. floppy disk or later hard disk) and a name. Once HFS saw the 
  441. light of day, folders within folders became a reality, and you 
  442. needed a dirID as well to point out what folder you really meant 
  443. on the volume. However, older programs that wasn't being 
  444. rewritten still knew nothing about directory IDs, so Apple had 
  445. SFGetFile make up "fake" vRefNums that didn't just specify a 
  446.  
  447. volume, but also a parent folder. These are called wdRefNums 
  448. (for working directory) and were a necessary evil invented in 
  449. 1985. You should not create (or, indeed, use) wdRefNums 
  450. yourself. 
  451.  
  452. There is a system-wide table that maps wdRefNums onto 
  453. vRefNum/parID pairs. There is a limit to the size of this table. 
  454. A dirID and a parID is almost the same thing; you say "parID" 
  455. when you mean the folder something is in, while you say a 
  456. "dirID" when you mean the folder itself. If you for instance 
  457. have a folder called "Foo" with a folder called "Bar" in it, the 
  458. parID for "Bar" would be the dirID for "Foo." 
  459.  
  460. 1.4) Q: How do I convert a wdRefNum as returned by SFGetFile 
  461. into a vRefNum/parID pair to use with the HXxx calls. 
  462.  
  463. A: Use GetWDInfo, which is declared as: 
  464.  
  465. Pascal OSErr GetWDInfo ( short wdRefNum , short * vRefNum , long 
  466. * parID , OSType * procID ) ; 
  467.  
  468. The procID parameter must be non-NULL and point to an OSType 
  469. variable, but the value of that variable can and should be 
  470. ignored. 
  471.  
  472. It is recommended that, as soon as you get your hands on a 
  473. wdRefNum, for instance from SFGetFile, you directly convert it 
  474. into a vRefNum/parID pair and always use the latter to reference 
  475. the folder. 
  476.  
  477. 1.5) Q: How do I select a folder using SFGetFile? 
  478.  
  479. A: This requires a custom dialog with a filter proc. It is too 
  480. complicated to show here, but not totally impossible to 
  481. comprehend. There is sample code on ftp.apple.com, in the 
  482. directory dts/snippets, on how to do this. 
  483.  
  484. 1.6) Q: How do I get the full path of a file referenced by a 
  485. vRefNum, parID and name? 
  486.  
  487. A: You don't. 
  488.  
  489. OK, I cheated you. There is exactly ONE valid reason to get the 
  490. full path of a file (or folder, for that matter) and that is to 
  491. display its location to the user in, say, a settings dialog. To 
  492. actually save the location of the file you should do this: 
  493. (assuming the file is in an FSSpec called theFile - you can use 
  494. FSSpecs in your program even if you don't run under System 7; 
  495. just make your own MyFSMakeFSSpec that fills in the FSSpec 
  496. manually if it's not implemented) 
  497.  
  498. *code*
  499. if ( ! aliasManagerAvailable ) { /* System 6 ? */
  500.     GetVolumeName ( theFile -> vRefNum , vName ) ;
  501.     GetVolumeModDate ( vRefNum , & date ) ;
  502.     Save ( vName , date , parID , fileName ) ;
  503. } else {
  504.     NewAlias ( NULL , theFile , & theAlias ) ;
  505.     Save ( theAlias ) ;
  506.     DisposeHandle ( ( Handle ) theAlias ) ;
  507. }
  508. *end*
  509.  
  510. If you are really concerned about these issues (of course you 
  511. are!) you should save BOTH of these methods when available, and 
  512. load back whatever is there that you can handle; since users may 
  513. be using your application in a mixed System 6/System 7 
  514. environment. 
  515.  
  516. To get back to the file is left as an exercise for the reader. 
  517.  
  518. To open a file using fopen() or the Pascal equivalent, see above 
  519. about using and not using HSetVol. 
  520.  
  521. 1.7) Q: What about actually getting the full path for a file? I 
  522. promise I will only use it to show the location of a file to the 
  523. user! 
  524.  
  525. A: Enter PBGetCatInfo, the Vegimatic of the Mac file system. Any 
  526. Mac hacker of knowledge has taken this system call to his heart. 
  527. What you do is this: 
  528.  
  529. *code*
  530. OSErr
  531. GetFolderParent ( FSSpec * fss , FSSpec * parent ) {
  532.  
  533. CInfoPBRec rec ;
  534. short err ;
  535.  
  536.     * parent = * fss ;
  537.     rec . hFileInfo    . ioNamePtr = parent -> name ;
  538.     rec . hFileInfo    . ioVRefNum = parent -> vRefNum ;
  539.     rec . hFileInfo    . ioDirID = parent -> parID ;
  540.     if ( parent -> name [ 0 ] ) {
  541.         rec . hFileInfo . ioFDirIndex = 0 ;
  542.     } else {
  543.         rec . hFileInfo . ioFDirIndex = -1 ;
  544.     }
  545.     rec . hFileInfo    . ioFVersNum = 0 ;
  546.     err = PBGetCatInfoSync ( & rec ) ;
  547.     if ( ! ( rec . hFileInfo . ioFlAttrib & 0x10 ) ) { /* Not a folder */
  548.         if ( ! err ) {
  549.             err = dirNFErr ;
  550.         }
  551.     } else {
  552.         parent -> parID = rec . dirInfo . ioDrParID ;
  553.         parent -> name [ 0 ] = 0 ;
  554.     }
  555.     return err ;
  556. }
  557.  
  558.  
  559. OSErr
  560. GetFullPathHandle ( FSSpec * fss , Handle * h ) {
  561.  
  562. Handle  tempH = NULL ;
  563. short err ;
  564. FSSpec fs = * fss ;
  565.  
  566.     while ( fs . parID > 1 ) {
  567.         tempH = NULL ;
  568.         PtrToHand ( & fs . name [ 1 ] , & tempH , fs . name [ 0 ] ) ;
  569.         PtrAndHand ( ( void * ) ":" , tempH , 1 ) ;
  570.         HandAndHand ( * h , tempH ) ;
  571.         SetHandleSize ( * h , 0L ) ;
  572.         HandAndHand ( tempH , * h ) ;
  573.         DisposeHandle ( tempH ) ;
  574.         tempH = NULL ; 
  575.         GetFolderParent ( & fs , & sSpec ) ;
  576.         fs = sSpec ;
  577.     }
  578.     GetVolName ( fs    . vRefNum , fs . name ) ;
  579.     PtrToHand ( & fs . name [ 1 ] , & tempH , fs . name [ 0 ] ) ;
  580.     PtrAndHand ( ( void * ) ":" , tempH , 1 ) ;
  581.     HandAndHand ( * h , tempH ) ;
  582.     SetHandleSize ( * h , 0L ) ;
  583.     HandAndHand ( tempH , * h ) ;
  584.     DisposeHandle ( tempH ) ;
  585.     tempH = NULL ;
  586.     if ( ! IsFolder ( fss ) ) {
  587.     SetHandleSize ( * h , GetHandleSize ( * h ) - 1 ) ; // Remove colon }
  588.     return 0 ;
  589. }
  590. *end*
  591.  
  592. 1.8) Q: So how do I get the names of the files in a directory? 
  593.  
  594. A: You use PBGetCatInfo again, but this time you set ioFDirIndex 
  595. to 1 or more (you need to know the dirID and vRefNum of the 
  596.  
  597. folder you're interested in) You then call PBGetCatInfoSync for 
  598. values of ioFDirIndex from 1 and up, until you get an fnfErr. 
  599. Any other err means you are not allowed to get info about THAT 
  600. item, but you may be for the next. Then collect the names in the 
  601. string you made ioNamePtr point to as you go along. Note that 
  602. you need to fill in the ioDirID field for each iteration through 
  603. the loop, and preferrably clear the ioFVersNum as well. 
  604.  
  605. Note that the contents of a directory may very well change while 
  606. you are iterating over it; this is most likely on a file server 
  607. that more than one user uses, or under System 7 where you run 
  608. Personal File Share. 
  609.  
  610. 1.9) Q: How do I find the name of a folder for which I only know 
  611. the dirID and vRefNum? 
  612.  
  613. A: You call (surprise!) PBGetCatInfo! Make ioNamePtr point to an 
  614. empty string (but NOT NULL) of length 63 (like, an Str63) and 
  615. ioFDirIndex negative (-1 is a given winner) - this makes 
  616. PBGetCatInfo return information about the vRefNum/dirID folder 
  617. instead of the file/folder specified by vRefNum, parID and name. 
  618.  
  619. 1.10) Q: How do I make the Finder see a new file that I created? 
  620. Or if I changed the type of it; how do I display a new icon for 
  621. it? 
  622.  
  623. A: You call (surprise!) PBGetCatInfo followed by PBSetCatInfo 
  624. for the FOLDER the file is in. Inbetween, you should set 
  625. ioDrMdDat to the current date&time. Code: 
  626.  
  627. *code*
  628. OSErr
  629. TouchFolder ( short vRefNum , long parID ) {
  630.  
  631. CInfoPBRec rec ;
  632. Str63 name ;
  633. short err ;
  634.  
  635.     rec . hFileInfo . ioNamePtr = name ;
  636.     name [ 0 ] = 0 ;
  637.     rec . hFileInfo . ioVRefNum = vRefNum ;
  638.     rec . hFileInfo . ioDirID = parID ;
  639.     rec . hFileInfo . ioFDirIndex = -1 ;
  640.     rec . hFileInfo . ioFVersNum = 0 ;
  641.     err = PBGetCatInfoSync ( & rec ) ;
  642.     if ( err ) {
  643.         return err ;
  644.     }
  645.     GetDateTime ( & rec . dirInfo . ioDrMdDat ) ;
  646.     rec . hFileInfo . ioVRefNum = vRefNum ;
  647.     rec . hFileInfo . ioDirID = parID ;
  648.     rec . hFileInfo . ioFDirIndex = -1 ;
  649.     rec . hFileInfo . ioFVersNum = 0 ;
  650.     rec . hFileInfo . ioNamePtr [ 0 ] = 0 ;
  651.     err = PBSetCatInfoSync ( & rec ) ;
  652.     return err ;
  653. }
  654. *end*
  655.  
  656. 1.11) Q: Aren't we done with PBGetCatInfo soon? 
  657.  
  658. A: Well, it turns out that you can also find out whether an 
  659. FSSpec is a file or a folder by calling PBGetCatInfo and check 
  660. bit 4 (0x10) of ioFlAttr to see whether it is a folder. You may 
  661. prefer to call ResolveAliasFile for this instead. 
  662.  
  663. You can also check the script of the file's title using 
  664. PBGetCatInfo and check the ioFlFndrXInfo field if you want to 
  665. work with other script systems than the Roman system. 
  666.  
  667. Another common use is to find out how many items are in a 
  668. folder; the modification date of something or the correct 
  669. capitalization of its name (since the Mac file system is case 
  670. independent BUT preserves the case the user uses) 
  671.  
  672. 1.12) Q: How do I set what folder should initially be shown in 
  673. the SFGetFile boxes? 
  674.  
  675. A: You stuff the dirID you want to show into the lo-mem global 
  676. CurDirStore, and the NEGATIVE of the vRefNum you want into the 
  677. lo-mem global SFSaveDisk. 
  678.  
  679. If you are using CustomGetFile and return sfSelectionChanged 
  680. from an "init" message handler, you must remember to clear the 
  681. script code, else the selection will not change. 
  682.  
  683. 1.13) Q: How do I find the folder my application started from? 
  684. How do I find the application file that's running?
  685.  
  686. A: Under System 7, you call GetCurrentProcess, followed by 
  687. GetProcessInformation with a pointer to an existing FSSpec in 
  688. the parameter block. This will give you your file, and, by using 
  689. the vRefNum and parID, the folder the application is in.
  690.  
  691. Beware from writing to your applications resource or data forks; 
  692. the former breaks on CDs/write protected floppies/file 
  693. servers/virus checkers, the latter fails on PowerPC as well as 
  694. in the above cases.
  695.  
  696. *2* Serial ports 
  697.  
  698. 2.1) Q: How do I get at the serial ports? 
  699.  
  700. A: You call OpenDriver for the names "\p.AOut" and "\p.AIn" to 
  701. get at the modem port, and "\p.BOut" and "\p.BIn" for the 
  702. printer port. The function RAMSDOpen was designed for the 
  703. original Mac with 128 kB of memory and 64 kB of ROM, and has 
  704. been extinct for several years. 
  705.  
  706. However, many users use their serial ports for MIDI, LocalTalk, 
  707. graphic tablets, or what have you and have installed an 
  708. additional serial port card to get more ports. What you SHOULD 
  709. do as a good application is to use the Comms Toolbox Resource 
  710. Manager to search for serial resources; this requires that the 
  711. Comms Toolbox is present (true on earlier System 6 with an INIT, 
  712. on later System 6 and System 7 always, as well as on A/UX) and 
  713. that you have initialized the comms resource manager. The exact 
  714. code follows (adapted from Inside Mac Comms Toolbox): 
  715.  
  716. *code*
  717. #include <CommsResources.h>
  718. OSErr
  719. FindPorts ( Handle * portOutNames , Handle * portInNames , Handle * names , Handle * iconHandles ) {
  720.  
  721. OSErr ret = noErr ;
  722. short old = 0 ;
  723. CRMRec theCRMRec , * found ;
  724. CRMSerialRecord * serial ;
  725.  
  726.     * portOutNames = NewHandle ( 0L ) ;
  727.     * portInNames = NewHandle ( 0L ) ;
  728.     * names = NewHandle ( 0L ) ;
  729.     * iconHandles = NewHandle ( 0L ) ;
  730.     while ( ! ret ) {
  731.         theCRMRec . crmDeviceType = crmSerialDevice ;
  732.         theCRMRec . crmDeviceID = old ;
  733.         found = ( CRMRec * ) CRMSearch ( ( QElementPtr ) & theCRMRec ) ;
  734.         if ( found ) {
  735.             serial = ( CRMSerialRecord * ) found -> crmAttributes ;
  736.             old = found -> crmDeviceID ;
  737.             PtrAndHand ( & serial -> outputDriverName , * portOutNames ,
  738.                 sizeof ( serial -> outputDriverName ) ) ;
  739.             PtrAndHand ( & serial -> inputDriverName , * portInNames ,
  740.                 sizeof ( serial -> inputDriverName ) ) ;
  741.             PtrAndHand ( & serial -> name , * names , 
  742.                 sizeof ( serial -> name ) ) ;
  743.             PtrAndHand ( & serial -> deviceIcon , * iconHandles ,
  744.                 sizeof ( serial -> deviceIcon ) ) ;
  745.         } else {
  746.             break ;
  747.         }
  748.     }
  749.     return err ;
  750. }
  751. *end*
  752.  
  753. This will create four handles with the driver names, device 
  754. names and driver icon handles for all of the available serial 
  755. devices. Then let the user choose with a pop-up menu or 
  756. scrolling list, and save the choice in your settings file. 
  757.  
  758. You can use OpenDriver, SetReset, SetHShake, SetSetBuf, 
  759. SerGetBuf and the other Serial Manager functions on these 
  760. drivers. To write to the serial port, use FSWrite for 
  761. synchronous writes that wait until all is written, or PBWrite 
  762. asynchronously for queuing up data that is supposed to go out 
  763. but you don't want to wait for it. At least once each tim 
  764.  
  765. e through your event loop, you should call SerGetBuf on the in 
  766. driver reference number you got from OpenDriver, and call FSRead 
  767. for that many bytes - neither more nor less. 
  768.  
  769. If you are REALLY interested in doing the right thing, you will 
  770. use the Communications Toolbox Connection Manager instead; this 
  771. will give you access to modems, direct lines, and networks of 
  772. various kinds using the same API! Great for stuff like BBSes 
  773. that may be on a network as well etc. The Comms Toolbox also 
  774. priovides modularized terminal emulat 
  775.  
  776. ion and file transfer tools, although the Apple-suplied VT102 
  777. tool is pretty lame, as is the VT102 mode of the VT320 tool. 
  778.  
  779. *3* TCP/IP and sockets 
  780.  
  781. 3.1) Q: Where is a Berkley sockets library for the Mac? 
  782.  
  783. A: There are some problems with that. MacTCP, the Mac Toolbox 
  784. implementation of TCP/IP, doesn't have an API that looks at all 
  785. like Berkley sockets. For instance, there is ONE paramater-block 
  786. call to do a combined listen()/accept()/bind() - sort of. I have 
  787. heard that there may be a socket library available by ftp from 
  788. MIT but haven't seen it myself. 
  789.  
  790. There is also a pretty good C++ TCP implementation called GUSI 
  791. which is easily handled, and it also is callable from C using 
  792. the Berkley socket API. Apart from TCP, it also handles 
  793. "standard" Mac network protocols such as ADSP. The big 
  794. disadvantage is that it is currently only implemented for MPW. 
  795. The ftp site is nic.switch.ch, software/mac/src/mpw_c. 
  796.  
  797. I can also recommend the Communications Toolbox; for the price 
  798. of using an API that is simpler than the Berkley sockets, you 
  799. get the benefit of being able to use any kind of connection (TCP 
  800. tools are available) 
  801.  
  802. Novell and Wollogong offer commercial socket-like libraries. 
  803.  
  804. 3.2) Q: Where do I find MacTCP? 
  805.  
  806. A: You can buy the MacTCP developers kit from APDA. It is also 
  807. available on E T O, and if you want saner headers than those, 
  808. try ftp to seeding.apple.com. 
  809.  
  810. *4* AppleEvents and the AppleEvent Object Model 
  811.  
  812. 4.1) Q: What are AppleEvents? 
  813.  
  814. A: AppleEvents are a level-5 network protocol. If you are not 
  815. familiar with the ISO network stack, this means it's a way of 
  816. structuring sessions between network entities (programs) that is 
  817. not dependent on the underlying protocol (such as PPC or TCP/IP) 
  818. Despite being a network protocol, they can be very useful on 
  819. Macs that are not on a network. In short, they provide 
  820. applications with a comprehensive way to send arbitrary 
  821. structured data to other applications (or themselves) which 
  822. receive the events through their main event loop. 
  823.  
  824. The AppleEvent Object Model is a way of looking at applications 
  825. and the data they contain, and also a level-6 network protocol. 
  826. You _can_ send AppleEvent Object Model data through AppleEvents 
  827. (and the standard AppleEvents defined in the AppleEvent Registry 
  828. use it) but you don't have to - unless you want to talk with 
  829. other applications, of course, then the AEOM is a lingua franca. 
  830. 4.2) Q: What are the four required AppleEvents? 
  831.  
  832. A: There are four events your application really must implement 
  833. if you want to sell it: the kCoreEventClass class, 
  834. kAEOpenApplication, kAEQuitApplication, kAEOpenDocuments and 
  835. kAEPrintDocuments events IDs. When you support these events (or 
  836. any AppleEvents) you will not get startup info through 
  837. GetAppParams() anymore, unless you run under System 6 of course. 
  838. The kAEOpenApplication event will be sent to you when the user 
  839. double-clicks your app and it's not started yet. When receiving 
  840. it, you can put up a new untitled window. 
  841.  
  842. kAEOpenDocuments is sent when the user double-clicks your apps 
  843. documents. Note that if the first AppleEvent you receive is a 
  844. kAEOpenDocuments event, the user started your app by 
  845. double-clicking its documents. 
  846.  
  847. kAEPrintDocuments is sent when the user selects your documents 
  848. and chooses "Print" in the Finder menu. If this is the first 
  849. AppleEvent you receive, you should print the documents and then 
  850. quit the application again; if you received a kAEOpenApplication 
  851. or kAEOpenDocuments event before this, you should just print the 
  852. documents and close them when you're done. 
  853.  
  854. kAEQuitApplication is sent to you when the user chooses 
  855. "Shutdown" or "Restart" from the Apple Menu. You should ask the 
  856. user whether he wants to save any unsaved changed documents, and 
  857. then quit unless the user presses Cancel. 
  858.  
  859. Interestingly enough, you can use these four AppleEvents to send 
  860. even to non-AE-aware applications, and the system will translate 
  861. these events into fake menu selections for you. 
  862.  
  863. A good way of shutting down the Finder is to send it a Quit 
  864. AppleEvent. You should send a Quit AppleEvent to File Sharing 
  865. Extension before you shut down the Finder, though; the FSE is 
  866. found by looking for a process with the creator 'hhgg'. 
  867.  
  868. 4.3) Q: Are there any limits or tradeoffs with AppleEvents? 
  869.  
  870. A: As always, more power means more responsibility. 
  871.  
  872. AppleEvents sent to applications on other Macs require 
  873. authentification the first time they are sent. If the remote Mac 
  874. allows Guests to link to programs, the INIT AutoGuest 2.0 might 
  875. help (or the code solution that comes with it and you can build 
  876. into your application) 
  877.  
  878. In the first version of the AppleEvent manager, there was a 
  879. total 64K limit on the size of data and overhead. This limit has 
  880. been lifted with the version of the AppleEvent manager that 
  881. comes with AppleScript. 
  882.  
  883. AppleEvents require a lot of memory copying and handle resizing 
  884. in their construction; this means that large AppleEvents may be 
  885. slow in construction, especially when compared to a pure PPC 
  886. Toolbox or ADSP/ASDSP link. 
  887.  
  888. You should use your own application signature as event class for 
  889. AppleEvents you make up, in order not to collide with anybody 
  890. else. Other than that, you are free to make your own events for 
  891. your own needs, though supporting the required events and at 
  892. least a subset of the Core event suite will buy you a lot of 
  893. functinality from within AppleScript. Especially important are 
  894. the Get Current Selection and Set Current Selection events 
  895. (which are really Get/Set Data on the contents of the current 
  896. selection of the application) 
  897.  
  898. The signature for your application SHOULD be registered with DTS 
  899. to avoid conflicts; this is done through e-mail to 
  900. DEVSUPPORT@AppleLink.Apple.Com and the form you use is located 
  901. on the developer CDs and found on ftp.apple.com. 
  902.  
  903. *5* AppleScript 
  904.  
  905. 5.1) Q: How does AppleEvents interface with AppleScript? 
  906.  
  907. A: AppleEvents are the meat and potatoes of AppleScript. If you 
  908. support the AppleEvent Object Model from within your 
  909. application, users can control you through AppleScript. 
  910.  
  911. The first thing you should do is get ahold of Inside Mac: 
  912. Interapplication Communication, and a copy of the AppleEvents 
  913. Registry. The former tells you all you ever need to know about 
  914. AppleEvents, while the latter is paramount for implementing the 
  915. right standard events. If everybody use the standard events, 
  916. dynamic data interchange between any applications will become 
  917. sweet reality! 
  918.  
  919. Then there is the 'aete' resource which lets you put names on 
  920. the events you support, so that users can "Open Terminology" on 
  921. your application from within the Apple Script Editor and use the 
  922. proper AppleScript commands in their scripts. The format of an 
  923. aete resource is defined in Inside Macintosh: Interapplication 
  924. Communication. 
  925.  
  926. 5.2) Q: Can I compile and run scripts from within my 
  927. application? 
  928.  
  929. A: Yes, this is very simple. There are toolbox calls for reading 
  930. scripts, compiling scripts, and executing scripts. (OSACompile, 
  931. OSAExecute) These are all documented in Inside Mac: 
  932. Interapplication Communication. 
  933.  
  934. 5.3) Q: Is this a good way of getting a macro language almost 
  935. for free? 
  936.  
  937. A: "Good" is an understatement. Just let users write scripts, 
  938. load them into menu items and go. Total systems integration in 
  939. under a week, including adding support for the AEOM to your 
  940. application. 
  941.  
  942. There is source code for an application called "MenuScipter" on 
  943. the developer CD which shows you how to do an application with 
  944. all of the menus being AppleScript scripts. 
  945.  
  946. *6* Drawing using QuickDraw 
  947.  
  948. 6.1) Q: Why is CopyBits so slow? 
  949.  
  950. A: It is not. It just requires some hand-holding to get good 
  951. results. The main rules are: Make sure the source and 
  952. destination pixMaps are of the same depth. 
  953.  
  954. Make sure the front color is black and the back color is white. 
  955.  
  956. Use srcCopy and don't use a masking region. 
  957.  
  958. Copy to an unclipped window (the frontmost window). 
  959.  
  960. Make sure the ctSeed values of the source pixMap and dest pixMap 
  961. match. 
  962.  
  963. Copying few and large pixMaps is faster than copying many and 
  964. small ones. Icon-sized sprites count as small ones. 
  965.  
  966. Make sure your source bitmap or pixelMap has the same alignment, 
  967. when adjusted for the source and destination rect expressed in 
  968. global screen coordinates. The necessary alignment is 32 bits (4 
  969. bytes), although 128 bit (16 byte) alignment is probably even 
  970. better on 68040 macs and won't hurt on other macs. 
  971.  
  972. Example of global alignment: 
  973.  
  974. Your window is positioned at (42,100) (H,V) 
  975.  
  976. Your destination rectangle is (10,20)-(74,52) 
  977.  
  978. The alignment coefficient of the rectangle in global coordinates 
  979. is (42+10)*bitDepth where bitDepth is one of 1,2,4,8,16 or 32. 
  980.  
  981. Make sure your source pixmap rect has the same coeffecient 
  982. modulo your alignment factor (in bits) For black&white macs, 
  983. this is still true, although bitDepth is fix at 1. Offscreen 
  984. pixMaps can calculate with a "global posistion" of 0,0 and get 
  985. correct results. 
  986.  
  987. 6.2) Q: Why is CopyBits still too slow? 
  988.  
  989. A: Because there is always some overhead involved in calling 
  990. QuickDraw; you have the trap dispatcher, clipping checks, and 
  991. checking whether the CopyBits call is being recorded in a PICT 
  992. handle (if you called OpenPicture) 
  993.  
  994. If you can't live with this, look at *7* below, but PLEASE try 
  995. and make CopyBits work, and retain the CopyBits code in your 
  996. application, so users with special monitors (accellerator cards, 
  997. PowerBook color screens, Radius Pivot screens) can still play 
  998. your game. (non-game applications don't need more speed than 
  999. CopyBits can give at its max. Promise!) 
  1000.  
  1001. 6.3) Q: What is the fastest way to set one pixel? 
  1002.  
  1003. A: NOT SetCPixel()! Assuming you have the correct ForeColor() 
  1004. set, you can set the pen size to (1,0) and call Line (0,1) 
  1005.  
  1006. I have heard PaintRect is good for this but requires slightly 
  1007. more code.  Using PaintRect eliminates a trap call. 
  1008.  
  1009. 6.4) Q: Why do pictures I record suddenly draw as empty space or 
  1010. not draw at all? 
  1011.  
  1012. A: When recording pictures, you have to set the clipping area to 
  1013. exactly the frame of the picture you are recording. This is 
  1014. because it is initally set at -32768,32727 in both directions, 
  1015. and offsetting the picture even one pixel when drawing it will 
  1016. result in the region wrapping around and becoming empty. 
  1017.  
  1018. When recording pictures, do this: 
  1019.  
  1020. *code*
  1021. PicHandle h = OpenPicture ( & theRect ) ;
  1022. ClipRect ( & theRect ) ;
  1023.     /* draw the picture */
  1024. ClosePicture ( ) ;
  1025. *end*
  1026.  
  1027. 6.5) Q: Where can I find the format of picture files and 
  1028. resources? 
  1029.  
  1030. A: The format of a picture resource version 1 is defined in a 
  1031. technical note. This format is obsolete. 
  1032.  
  1033. The format of a picture resource version 2 is defined in Old 
  1034. Inside Mac vol V, with addenda in Old Inside Mac vol VI. 
  1035.  
  1036. Some things happen with QuickTime compressed pictures; try the 
  1037. Inside Mac: QuickTime book or wait for Inside Mac: Imaging which 
  1038. is the definite reference on QuickDraw. 
  1039.  
  1040. The format of a picture file is the same as that of a picture 
  1041. resource with 512 added 0 bytes in front. 
  1042.  
  1043. 6.6) Q: GWorlds? 
  1044.  
  1045. A: What about them? They're great. Look them up in Old Inside 
  1046. Mac vol VI. Don't forget to SetGWorld back to what it was before 
  1047. calling WaitNextEvent. 
  1048.  
  1049. 6.7) Q: How do I find the current depth of the screen? 
  1050.  
  1051. A: My question to you is: What screen? Many macs have more than 
  1052. one screen attached. You can use GetDeviceList and walk the 
  1053. devices to find the screen you're looking for (use 
  1054. TestDeviceAttrib to see whether it's a screen) or you can call 
  1055. GetMaxDevice() to find the deepest device your window 
  1056. intersects. 
  1057.  
  1058. Once you have the device handle, finding the depth is just a 
  1059. matter of looking at the dgPMap pixMapHandle, and dereference it 
  1060. to the pmSize field. Done. 
  1061.  
  1062. *7* Drawing directly to screen 
  1063.  
  1064. 7.1) Q: Why is it a bad idea to draw directly to screen? 
  1065.  
  1066. A: Because of several reasons: 
  1067.  
  1068. - You will be incompatible with future display hardware. 
  1069.  
  1070. - You will be incompatible with some present-day display 
  1071. hardware, such as Radius Pivots and PowerBook color screens. 
  1072.  
  1073. - You have to think about a lot of things; testing it all on 
  1074. your own machine is not possible and the chances of crashing are 
  1075. great. 
  1076.  
  1077. - You will be incompatible with future hardware where devices 
  1078. may live in some unaccessible I/O space. 
  1079.  
  1080. 7.2) Q: But I really need to do it. I can't make my animation 
  1081. into a QuickTime movie, and CopyBits is too slow, even when 
  1082. syncing to the screen retrace. 
  1083.  
  1084. A: You have to prepare yourself, and ask these questions: 
  1085.  
  1086. 1) Do I want to support all screens, or just 8-bit devices? 
  1087.  
  1088. 2) Do I have a few weeks of free time to make it work? 
  1089.  
  1090. 3) Do I want to get nasty mail when I break on some hardware and 
  1091. have to rev the application - even if I may not be able to get 
  1092. ahold of the hardware that makes it break? 
  1093.  
  1094. If all you're doing is rendering an image pixel-by-pixel or 
  1095. line-by-line, maybe you can draw directly into an offscreen 
  1096. pixMap/GWorld and then CopyBits the entire GWorld to screen? 
  1097. That will be more compatible, especially if you use the 
  1098. keepLocal flag when creating the GWorld. 
  1099.  
  1100. 7.3) Q: Okay, so how do I get the base address of the screen? 
  1101.  
  1102. A: "The" screen? Which screen? There may be several. The base 
  1103. address may be on an accellerated screen card. There may be more 
  1104. than one screen covering the same desktop area. 
  1105.  
  1106. Due to unfortunate circumstances, there is a bug in 
  1107. GetPixBaseAddr() that causes it to return incorrect results for 
  1108. some versions of System 7. Instead, get the baseAddr directly 
  1109. from the gdPMap handle of the GDHandle for the screen you draw 
  1110. to. This address may need switching to 32bit mode to be valid. 
  1111.  
  1112. 7.4) Q: Quit stalling and give me code! 
  1113.  
  1114. A: Okay, but I'll let you sweat over Inside Mac to figure out 
  1115. what it does. All of it is important; believe me! To make this 
  1116. code run faster, a lot of the things it does can be done once 
  1117. before starting to draw. 
  1118.  
  1119. Make sure that you have a window that covers the area where you 
  1120. are drawing, so other windows will not be overdrawn. Also make 
  1121. sure that you do not do direct-to-screen-drawing while you are 
  1122. in the background. 
  1123.  
  1124. *code*
  1125. /* This is presently untested code */
  1126. /* Value is dependent on what depth the screen has */
  1127. /* This code doesn't work on non-color-quickdraw Macs (i e the MacClassic) */
  1128. /* "where" is in GLOBAL coordinates */
  1129. void
  1130. SetPixel ( Point where , unsigned long value ) {
  1131.  
  1132. Rect r ;
  1133. GDHandle theGD ;
  1134. char * ptr ;
  1135. long rowBytes ;
  1136. short bitsPerPixel ;
  1137. PixMapHandle pmh ;
  1138. Boolean oldMode ;
  1139.  
  1140.     r . left = where . h ;
  1141.     r . top = where    . v ;
  1142.     r . right = r . left + 1 ;
  1143.     r . bottom = r . top + 1 ;
  1144.     theGD = GetMaxDevice ( & r ) ;
  1145.     if ( theGD ) {
  1146.         where . v -= ( * theGD ) -> gdRect . left ;
  1147.         where . h -= ( * theGD ) -> gdRect . top ;
  1148.         pmh = ( * theGD ) -> gdPMap ;
  1149.         rowBytes = ( ( * pmh ) -> rowBytes ) & 0x3fff ;
  1150.         ptr = ( char * ) ( * pmh ) -> baseAddr ;
  1151.         bitsPerPixel = ( * pmh ) -> pixelSize ;
  1152.         oldMode = true32b ;
  1153.         ptr += where . v * rowBytes ;
  1154.         SwapMMUMode ( & oldMode ) ;
  1155.         switch ( bitsPerPixel ) {
  1156.         case 1 :
  1157.             if ( value & 1 ) { 
  1158.                 ptr [ where . h >> 3 ] |= ( 128 >> ( where . h & 7 ) ) ;
  1159.             } else {
  1160.                 ptr [ where . h >> 3 ] &= ~( 128 >> ( where . h & 7 ) ) ;
  1161.             }
  1162.             break ;
  1163.         case 2 :
  1164.             ptr [ where . h >> 2 ] &= ( 192 >> 2 * ( where . h & 3 ) ) ;
  1165.             ptr [ where . h >> 2 ] |= ( value & 3 ) << 2 * ( 3 - ( where . h & 3 ) ) ;
  1166.             break ;
  1167.         case 4 :
  1168.             ptr [ where . h >> 1 ] &= ( where . h & 1 ) ? 0xf : 0xf0 ;
  1169.             ptr [ where . h >> 1 ] |= ( value & 15 ) << 4 * ( 1 - ( where . h & 1 ) ) ;
  1170.             break ;
  1171.         case 8 :
  1172.             ptr [ where . h ] = value ;
  1173.             break ;
  1174.         case 16 :
  1175.             ( ( unsigned short * ) ptr ) [ where . h ] = value ;
  1176.             break ;
  1177.         case 32 :
  1178.             ( ( unsigned long * ) ptr ) [ where . h ] = value ;
  1179.             break ;
  1180.         default :
  1181.             abort ( ) ; /* Should never get here */
  1182.         }
  1183.         SwapMMUMode ( & oldMode ) ;
  1184.     }
  1185. }
  1186. *end*
  1187.  
  1188. *8* Cache issues and other processor differences 
  1189.  
  1190. 8.1) Q: Why does my application work on an SE with accellerator 
  1191. (or a Mac II or Quadra), but not on one without? 
  1192.  
  1193. A: Assuming you're not calling Color QuickDraw (which is not 
  1194. available on accellerated SEs), you most probably have an 
  1195. odd-aligned word access somewhere. 
  1196.  
  1197. The 68000 does not allow words or longwords to be read from odd 
  1198. addresses, while the 68020 and up relaxes this restriction (it 
  1199. still is slower than aligned-word access though) 
  1200.  
  1201. This may or may not crash depending on your compiler: 
  1202.  
  1203. *code*
  1204. struct foo {
  1205.     char c1 ;
  1206.     char c2 ;
  1207.     char c3 ;
  1208.     char c4 ;
  1209.     char c5 ;
  1210. } bar ;
  1211.  
  1212.     long * x = ( long * ) & bar . c2 ;
  1213.     * x = 0x12345678 ; /* X is odd if compiler doesn't pad */
  1214.  
  1215. This WILL crash on an SE/Plus/Classic/PB100:
  1216.  
  1217. char foo [ 10 ] ;
  1218.  
  1219.     long * x = ( long * ) & foo [ 1 ] ;
  1220.     * x = 0x12345678 ;
  1221.  
  1222. *end*
  1223.  
  1224. 8.2) Q: Why does my application work on a IIci but not on a 
  1225. Quadra? 
  1226.  
  1227. A: Two reasons: 
  1228.  
  1229. 1) The Quadras 900 and 950 have special processors that handle 
  1230. the serial ports; if you write directly to the serial chips, you 
  1231. will crash (this goes for the IIfx as well) 
  1232.  
  1233. 2) The Quadras have 68040 processors, as have the Centrises. 
  1234. These processors have separate instruction and data caches (like 
  1235. the 68030) but they are larger (4K each) and unlike the 68030 
  1236. which is write-through data cached, the 68040 is copy-back data 
  1237. cached. This means that changes you make to "your code" aren't 
  1238. really changed all the time, since the changes may still be in 
  1239. the data cache and not written to memory when the CPU reads that 
  1240. part of memory into its I-cache. Even worse; that part might 
  1241. already have been read into the I-cache before you change it in 
  1242. the D-cache, meaning that writing out the D-cache will still not 
  1243. be enough. You need to flush both the caches when writing 
  1244. self-modifying code. 
  1245.  
  1246. Self-modifying code includes code that builds its own jump 
  1247. tables and code that decrypts itself and code that "stubs" MDEFs 
  1248. or WDEFs to jump back into the application code. 
  1249.  
  1250. You flush the cache using FlushDataCache() which is implemented 
  1251. if Gestalt says you have a 68020 or better processor (or if the 
  1252. _HwDispatch trap is implemented) 
  1253.  
  1254. 8.3) Q: Why does my application work on my Quadra but not on my 
  1255. accellerated SE? 
  1256.  
  1257. A: You're probably calling Color QuickDraw without first 
  1258. checking if it's available. The following machines do not have 
  1259. color QuickDraw in ROM nor RAM: 
  1260.  
  1261. Mac Plus, Mac SE, Mac Classic, Mac Luggable, PowerBook 100, 
  1262. Outbound 
  1263.  
  1264. 8.4) Q: I do check for color quickdraw, but crash nevertheless. 
  1265.  
  1266. A: _Gestalt lies under some versions of System 7; it says that 
  1267. non-color machines HAVE color QuickDraw when you test using the 
  1268. gestaltQuickdrawFeatures selector. 
  1269.  
  1270. Instead, check the gestaltQuickdrawVersion selector, if it 
  1271. returns >= gestalt8BitQuickdraw then you can safely use 
  1272. gestaltQuickdrawFeatures, else you only have b/w QuickDraw. 
  1273.  
  1274. 8.5) Q: Why are there no C/C++ compilers that optimize for the 
  1275. Mc68040? 
  1276.  
  1277. A: Beats me; optimizing for the 68040 can make programs up to 
  1278. 50% faster on that chip while still losing nothing, or very 
  1279. little (less than 10%) on older chips. 
  1280.  
  1281. *9* Inflammatory subjects 
  1282.  
  1283. 9.1) Q: What about pre-emptive multitasking? 
  1284.  
  1285. A: To the user, the Mac multitasking method, which builds upon 
  1286. each application calling WaitNextEvent, GetNextEvent or 
  1287. EventAvail every so often and the Process Manager/MultiFinder 
  1288. switching applications only at such calls, is at least as good 
  1289. as preemtive multitasking, because the present system 
  1290. priotitizes user interface responsiveness over everything else. 
  1291. The only shortfall about this is formatting floppies, which 
  1292. locks up the Mac CPU. This is because the Mac floppy controller 
  1293. is really stupid, and would happen even if the Mac multitasked 
  1294. preemptively. 
  1295.  
  1296. There IS "real" pre-emptive multitasking available for use in 
  1297. Mac applications; the expensive way is buying A/UX 3.0 which can 
  1298. have Mac applications written as UNIX processes; the cheap way 
  1299. is installing the Thread Manager which will allow you to create 
  1300. pre-emptive threads. However, the restrictions on those threads 
  1301. are the same as those on Time Manager tasks: don't call any 
  1302. function in an unloaded segment, and don't call QuickDraw or any 
  1303. toolbox call which may move memory (which are most ToolBox 
  1304. calls; paradoxally, BlockMove is safe :-) as are, surprisingly, 
  1305. FSRead and FSWrite) 
  1306.  
  1307. There are several problems with making the Mac OS preemptive; 
  1308. including apps that draw outside their windows or directly to 
  1309. screen, user dragging and other issues. 
  1310.  
  1311. 9.2) Q: What about protected memory? I'm sick and tired of 
  1312. re-booting when my application crashes. 
  1313.  
  1314. A: Write better software! 
  1315.  
  1316. Or install The Debugger from Jasik Designs, which can provide 
  1317. your application with write-protection of critical parts of 
  1318. memory. This may only work for 030 Macs, though. 
  1319.  
  1320. Making the Mac OS memory-protected is tricky, because 
  1321. applications expect to be able to write to low memory, the 
  1322. system heap, temporary memory, window lists, and even each 
  1323. other's heaps in some interapplication communication solutions 
  1324. that date back to before AppleEvents and the PPC Toolbox. 
  1325.  
  1326. *10* Handles; they are driving me crazy 
  1327.  
  1328. 10.1) Q: What is a handle? 
  1329.  
  1330. A: A handle is a pointer to a pointer to something. However, it 
  1331. is more than that; creating a handle by taking the address of 
  1332. one of your own pointers does NOT create a Handle; the Memory 
  1333. Manager will only deal properly with Handles that are created 
  1334. using NewHandle or something that calls it (such as NewRgn or 
  1335. GetResource) 
  1336.  
  1337. 10.2) Q: When do I have to lock a Handle? 
  1338.  
  1339. A: The contents of a Handle may move, and when it does, the 
  1340. pointer your handle is pointing to is changed to point to the 
  1341. new address so your handle is always valid. The toolbox may call 
  1342. the memory manager to allocate more memory pretty much anytime 
  1343.  
  1344. you call it (the toolbox) and when memory is allocated, your 
  1345. handle may move in memory. Don't dereference a handle into a 
  1346. pointer (or take the address of a field in a record a handle is 
  1347. double-pointing to) and then call the toolbox and expect the 
  1348. pointer to still be valid. The only way to ensure that the 
  1349. pointer will still be valid is to call HLock on the handle to 
  1350. lock it. 
  1351.  
  1352. Use HGetState and HSetState to save & restore the "locked" state 
  1353. of a handle when you lock it. 
  1354.  
  1355. 10.3) Q: How do I dispose of Handles? 
  1356.  
  1357. A: DisposeHandle (formerly called DisposHandle) once and ONLY 
  1358. once will do the trick. Trying to dispose of an already disposed 
  1359. Handle is an error. DoubleTrouble (see above) will catch such 
  1360. bugs when they do occur. 
  1361.  
  1362. 10.4) Q: What about resources? 
  1363.  
  1364. A: Calling GetResource returns NULL if the resource is not found 
  1365. or there is not enough memory, else it returns a handle to the 
  1366. resource. This handle may be moved or locked like any other 
  1367. handle, but DO NOT call DisposeHandle to get rid of a resource 
  1368. handle - call ReleaseResource. DisposeResource (see above) will 
  1369. catch this kind of bug. 
  1370.  
  1371. Remember that AddResource makes a resource handle out of an 
  1372. ordinary handle, and RmveResource or DetachResource makes an 
  1373. ordinary handle out of a resource handle. You cannot call 
  1374. AddResource with a resource handle; you have to DetachResource 
  1375. it first. 
  1376.  
  1377. Resource handles are automagically disposed when the resource 
  1378. file they belong to is closed. 
  1379.  
  1380. 10.5) Q: I'm trying to use a largish array in Think C, but get a 
  1381. "code overflow" error. This is valid C, why doesn't it work? 
  1382.  
  1383. A: The ANSI standard does not guarantee that any structure 
  1384. larger than 32767 bytes be correctly handled. Because of 
  1385. historical constraints, the Mac memory model is built around 
  1386. several small blocks of size 32K or less; these are used both 
  1387. for code and global/static data. If you want to use more code or 
  1388. data, you have to turn on "far code" or "far data" - you still 
  1389. will not get around the restriction of 32K code or data per 
  1390. compiled file, though. 
  1391.  
  1392. As opposed to, say, DOS or Windows, however, you can allocate as 
  1393. much memory as you want (and there is in the machine) and step 
  1394. through it using ordinary pointers; it's just that global and 
  1395. static data space is addressed off the A5 register using a 16bit 
  1396. displacement addressing mode in the 68000 processor. 
  1397.  
  1398. *11* _Gestalt and compatibility 
  1399.  
  1400. 11.1) Q: I see all these people call Gestalt without first 
  1401. checking whether it's implemented. Isn't that bad? 
  1402.  
  1403. A: No; Gestalt and a few other traps (the HXxx file manager 
  1404. traps, and FindFolder) are implemented using glue so they do the 
  1405. right thing even if the trap is not implemented. 
  1406.  
  1407. If you want to get rid of the glue, you can #define 
  1408. SystemSevenOrLater (and, using Think C/C++, re-pre-compile 
  1409. MacHeaders) However, then you will be responsible for checking 
  1410. for these features before you use them. 
  1411.  
  1412. 11.2) Q: What more functions are implemented in glue? 
  1413.  
  1414. A: Wake Up and Smell the Glue! [by Matthias Neeracher] 
  1415.  
  1416. How often have you wished you could use that cool new ToolBox 
  1417. call, but didn't want to make your application System 7 
  1418. dependent? Well, it might be that you *could* in fact have used 
  1419. the call. Several traps are implemented in glue, that is, much 
  1420. of their functionality is linked into your application and thus 
  1421. available even if you are running under an old System. 
  1422.  
  1423. This list applies to MPW 3.2 and should also be valid for the 
  1424. current version of Think C. If you find any inaccuracies, please 
  1425. report them to me. (neeri@iis.ee.ethz.ch) 
  1426.  
  1427. FSOpen: Tries first OpenDF, then Open. 
  1428.  
  1429. HOpenResFile: Full functionality emulated if trap not available 
  1430.  
  1431. HCreateResFile: Full functionality emulated if trap not 
  1432. available 
  1433.  
  1434. FindFolder: Under System 6, understands the following values for 
  1435. folderType and returns the System Folder for all of them: 
  1436.  
  1437. kAppleMenuFolderType 
  1438.  
  1439. kControlPanelFolderType 
  1440.  
  1441. kExtensionFolderType 
  1442.  
  1443. kPreferencesFolderType 
  1444.  
  1445. kPrintMonitorDocsFolderType 
  1446.  
  1447. kStartupFolderType 
  1448.  
  1449. kSystemFolderType 
  1450.  
  1451. kTemporaryFolderType 
  1452.  
  1453. SysEnvirons: Full functionality emulated if trap not available 
  1454.  
  1455. NewGestalt: Returns an error if not implemented 
  1456.  
  1457. ReplaceGestalt: Returns an error if not implemented 
  1458.  
  1459. Gestalt: The following selectors are always implemented: 
  1460.  
  1461. vers    mach    sysv    proc    fpu     
  1462.  
  1463. qd      kbd     atlk    ram     lram    
  1464.  
  1465. 11.3) Q: I have to support System 6, don't I? 
  1466.  
  1467. A: It would be foolish to lock yourself out of the many benefits 
  1468. the System 7 API provides for software that you start to write 
  1469. now. Some of the System 6 and older things (likely SFGetFile and 
  1470. wdRefNums among others) will be phased out of the interfaces and 
  1471. lose support; especially on future platforms. 
  1472.  
  1473. The installed base of System 7 is larger than that of System 6; 
  1474. this is not surprising because Apple has been shipping System 7 
  1475. for several years with all new machines, including the LCII, 
  1476. Classic II, Performas and Color Classic. Another argument is 
  1477. that newer computer owners (having System 7) are much more 
  1478. likely to buy new software than old computer owners who have 
  1479. systems that already do what they want them to. 
  1480.  
  1481. The added work to support both System 6 and System 7 is 
  1482. significant; if you have the time and money you may want to do 
  1483. it, but only supporting System 6 and not System 7 is doomed to 
  1484. fail in the market of today. 
  1485.  
  1486. Some may call this position subjective; I call it business sense 
  1487. based on market demographics. A rule of thumb may be that if you 
  1488. target color machines only, you can just as well demand System 7 
  1489. as well. 
  1490.  
  1491. *12* Standalone code and dynamic linking 
  1492.  
  1493. 12.1) Q: I've got a CODE resource off in limboland (sometimes 
  1494. called the resource fork) and I want to open it... what do I do? 
  1495. A: You open the file you have the code resource in, load the 
  1496. resource and lock it high (don't unlock it first, since someone 
  1497. else may be using it). Then you cast the handle to a function 
  1498. pointer, and call it normally. 
  1499.  
  1500. Suppose your code resource is compiled as a SACD id 128, and is 
  1501. defined as: 
  1502.  
  1503. *code*
  1504. long
  1505. main ( MyParams * params ) {
  1506.     switch ( params -> message ) {
  1507.     case messageInit :
  1508.         return init ( params ) ;
  1509.     ...
  1510.     }
  1511.     return 0L ;
  1512. }
  1513. *end*
  1514.  
  1515. Also suppose you already have the vRefNum, parID and name of the 
  1516. resource file you want to use. Do this: 
  1517.  
  1518. *code*
  1519.     setup_paramblock ( & the_params ) ;
  1520.     the_params . message = messageInit ;
  1521.     refNum = HOpenResFile ( vRefNum , parID , name , fsRdPerm ) ;
  1522.     if ( refNum < 1 ) {
  1523.         fail ( ResError ( ) ) ;
  1524.     }
  1525.     the_code = GetResource ( 'SACD' , 128 ) ;
  1526.     HLockHi ( the_code ) ;
  1527.     retval = ( * ( ( long ( * ) ( MyParams * ) ) StripAddress ( * the_code ) ) ) ( & the_params ) ;
  1528.     ...
  1529. *end*
  1530.  
  1531. The StripAddress is important; if your app is running in 24bit 
  1532. mode, the resource handle may contain tag bits and you don't 
  1533. want strange things to happen if the code resource switches into 
  1534. 32bit mode (which QuickDraw may do, incidentally)
  1535.  
  1536. Exactly how you structure your calling conventions is up to you; 
  1537. there is no accepted standard (except for HyperCard XCMDs, but 
  1538. that is probably overkill for you). 
  1539.  
  1540. *13* 
  1541.  
  1542. 13.1) Q: How do I read the modifier keys of the keyboard? 
  1543.  
  1544. A: Just call EventAvail and check the event.modifiers field. 
  1545. Only works when you are in the foreground. You can also use 
  1546. GetKeys(), or (as a last resort) check the lo-mem global KeyMap 
  1547. directly. 
  1548.  
  1549. 13.2) Q: How do I move the mouse cursor to a specific position?
  1550.  
  1551. A: Wait! Don't do it! There has to be a better way!
  1552.  
  1553. If you feel you HAVE to do it (for a game or VERY special
  1554. simulation situation) you can use the Cursor Device Manager
  1555. documented in the tech notes on ftp.apple.com. If that
  1556. manager is not installed, as it's not on older Macs, you can
  1557. use the following code:
  1558.  
  1559. ----- How to move the mouse (info in C): -----
  1560. you need to have some low-memory globals defined. they may be defined in
  1561. SysEqu.h.
  1562.  
  1563. #define MTemp 0x828
  1564. #define RawMouse 0x82c
  1565. #define CrsrNewCouple 0x8ce
  1566.  
  1567. note that CrsrNewCouple is actually a combination of two globals, just
  1568. to make our life slightly easier.
  1569.  
  1570. the code i use to move the mouse is:
  1571.  
  1572. *code*
  1573. void
  1574. MoveMouseTo ( Point where ) {
  1575.  
  1576.     HideCursor ( ) ;
  1577.     * ( Point * ) RawMouse = where ;
  1578.     * ( Point * ) MTemp = where ;
  1579.     * ( short * ) CrsrNewCouple = -1 ;
  1580.     ShowCursor ( ) ;
  1581. }
  1582. *end*
  1583.  
  1584. you need to hit a couple more global variables if you want this to
  1585. work properly in a multiple-monitor system, but i forget what they are 
  1586. offhand. poke through SysEqu.h, and you should be able to figure it out
  1587. without a problem.
  1588. ----------------------------------------------
  1589.  
  1590. On the PowerPC, these lo-mem globals may not be available for
  1591. native applications; however, all Power Macintoshes implement the
  1592. Cursor Device Manager.
  1593.  
  1594. There is also a file on nada.kth.se:pub/hacks/mac-faq/MoveMouse.c
  1595. which shows how to use the Cursor Device Manager, written by an
  1596. excellent Apple engineer. Grab!
  1597.  
  1598.  
  1599. *14* QuickTime 
  1600.  
  1601. 14.1) Q: I want to write a Amiga QuickTime player and need the 
  1602. CODEC format details. 
  1603.  
  1604. A: Although the structure of QuickTime movies is well documented 
  1605. in Inside Mac: QuickTime, the inner workings of the Apple 
  1606. compression modules is a trade secret that Apple will only 
  1607. license to you at great cost. Perhaps it's time for a freeware, 
  1608. cross-platform QuickTime codec? 
  1609.  
  1610. *15* Windows, Menus and Dialogs
  1611.  
  1612. 15.1) Q: My menus don't show up in the menu bar
  1613.  
  1614. A: If your menus are hiearchical, you'll have to install them
  1615. manually; GetNewMBar won't do it for you. See also 15.2.
  1616.  
  1617. 15.2) Q: When the user selects my menus, I get strange results
  1618. back; they seem to have different menu IDs than my menus?
  1619.  
  1620. A: The Menu ID as used by the menu manager is NOT the same
  1621. thing as the MENU resource ID (used in the MBAR resource and
  1622. with GetMenu()) When you create a MENU, ResEdit sets the menu
  1623. ID to the MENU resource ID, but if you re-number the resource,
  1624. you will have to open the menu in ResEdit and change the menu
  1625. ID usiung the "Edit MENU ID" menu item.
  1626.  
  1627. 15.3) Q: I use GetMenu() to find a menu in the menu bar, and then
  1628. change it, but it seems I have a memory leak OR my changes
  1629. don't "punch through"
  1630.  
  1631. A: GetMenu() is only intended if you don't already have the
  1632. menu "in memory." The call you should use almost all the time
  1633. is GetMHandle() which gets the handle to a menu in the current
  1634. menu bar by its menu ID (not resource id)
  1635.  
  1636. *16* Ice Cream and Frozen Yoghurt 
  1637.  
  1638. 16.1) Q: Dessert? 
  1639.  
  1640. A: Honey Hill Farms Cookie Jar Frozen Yoghurt or Haagen-Dazs 
  1641. Raspberry & Cream Ice Cream.
  1642.  
  1643. Hokey-Pokey icecream with chocolate sauce and (for those who 
  1644. like their brain food firmer) Almond and Double Chocolate 
  1645. CookieTime cookies!? [Denis Birnie]
  1646.  
  1647. *17* TextEdit [Chris Thomas, thunderone@delphi.com]
  1648.  
  1649. 17.1) Q: How the freakin' whelk do I get TextEdit to display more than 
  1650. 32k of text?
  1651.  
  1652. A: You don't.  Though theoretically possible through many awful hacks, no 
  1653. one's ever managed to do it.  Truly, it's not worth it.  There's a 
  1654. call-for-call TextEdit replacement called TE32k which does > 32k text, and 
  1655. is available from any recent Info-Mac mirror, as well as in the Delphi 
  1656. Developer SIG database.  It doesn't do styled text, though.
  1657.  
  1658. 17.2) Q: How the freakin' whelk do I get TextEdit to display more than 
  1659. 32k of __styled__ text?
  1660.  
  1661. There is a new library called WASTE which is available at 
  1662. ftp://ghost.dsi.unimi.it/pub2/papers/piovanel.  It's still alpha stage.
  1663.  
  1664. 17.3) Q: How do I include pictures in text using TextEdit?
  1665.  
  1666. A: There's no really easy way (such as a TEAddPict() call), and it will 
  1667. be a kludge if you do get it working, but if you can live with that, here's 
  1668. how to do it.
  1669.  
  1670. Write an algorithm to get the position of a special marker character or 
  1671. text attribute that the user will insert wherever it wants a picture.  
  1672. Pass this position to a function similar to the one below.
  1673.  
  1674. *code*
  1675.  
  1676. /*
  1677.     Draw a picture in a given textedit box.
  1678.     pos = the position of the special character in the text where the user 
  1679.     wants a picture.
  1680.     r = frame you want the picture to fit in.
  1681. */
  1682.  
  1683. void TEDrawPicture(short pos,PicHandle pic,Rect &r,TEHandle theTE)
  1684. {
  1685.     Point    bottomLeft;    //could be topleft, or whatever you want
  1686.     
  1687.     bottomLeft=TEGetPoint(pos,theTE);
  1688.     
  1689.     r.right=bottomLeft.h+(r.right-r.left);
  1690.     r.top=bottomLeft.v-(r.bottom-r.top);
  1691.     r.left=bottomLeft.h;
  1692.     r.bottom=bottomLeft.v;
  1693.     
  1694.     DrawPicture(pic,&r);
  1695. }
  1696.  
  1697. *end*
  1698.  
  1699. I'll leave selection and hiliting as an exercise for the reader.
  1700.  
  1701. Thereotically, it should be possible to kludge up TextEdit to the point 
  1702. where it would treat pictures as if they were actually letters (rather big 
  1703. letters, but letters just the same).  That's what the width and word break 
  1704. hooks are for, after all.  However, this would be a lot of Work, and I've 
  1705. never seen it done.  One is lead to believe that it's less work to create 
  1706. an improved version of TextEdit from the ground up with picture support.  
  1707. One could probably modify WASTE for this purpose, since the source is 
  1708. available.
  1709. -- 
  1710.  -- Jon W{tte, h+@nada.kth.se, Mac Software Engineer Deluxe --
  1711.  "If people bought cars according to the same principles they buy computers,
  1712.   cars would behave like Lamborghinis but would be built and look like Yugos."
  1713.                      -- Craig Fields
  1714.  
  1715.